using System.Collections.Generic;
using System.Data.Linq;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Magiq.Support;
using Magiq.Support.DynamicClasses;
using Magiq.Update;

namespace Magiq.Sql {
  public class UpdateExecutor : DynamicSelectQueryExecutor {
    private readonly IPropertySet samplePropertySet;

    public UpdateExecutor(DataContext dataContext, IQueryable where, IEnumerable<IPropertySet> propertySets)
      : base(dataContext, where, propertySets.Cast<IPropertyValueAssignment>(), true) {
      samplePropertySet = propertySets.First();
      Init(samplePropertySet.DeclaringType);
    }

    private void ProcessTypeReferenceBinding() {
      var expression = samplePropertySet.PropertyExpression;
      expression = expression.PreviousExpressionChain(true);
      var typeReferenceExpression = Expression.Property(expression.ChangeParameters(Parameter).Body,
                                                        (PropertyInfo) TypeReferenceMember.Member);

      Bindings.Add(Expression.Bind(DynamicClass.GetProperty(TypeReferenceName), typeReferenceExpression));
    }

    protected override List<DynamicProperty> CreateDynamicProperties() {
      var properties = base.CreateDynamicProperties();
      properties.Insert(0, new DynamicProperty(TypeReferenceName, TypeReferenceMember.Type));
      return properties;
    }

    protected override IEnumerable<string> GetCalculatedSqlValues() {
      return base.GetCalculatedSqlValues().Skip(1);
    }

    protected override void OnDynamicClassBuilt() {
      ProcessTypeReferenceBinding();
    }
  }
}